<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>函数对象的属性(Properties of function objects)</title>
  <!-- 
  在JavaScript中，函数是一种特殊的对象，具有一些独特的属性和方法。
  一、函数对象的基本特性
  1. 函数是一等公民：
    - 函数在JavaScript中被视为一等公民，可以作为参数传递给其他函数、作为返回值返回、并可以赋值给变量。

  2. 函数对象：
    - 每个函数都是一个对象，具有属性和方法。

  二、函数对象的属性
  1.  `length` ：
    -  `length` 属性表示函数定义时的参数个数。
    function example(a, b, c) {
        // ...
    }
    console.log(example.length); // 输出: 3
  2.  `name` ：
    -  `name` 属性返回函数的名称。如果函数是匿名的，则返回空字符串。
    function myFunction() {}
    console.log(myFunction.name); // 输出: "myFunction"

    const anonymousFunction = function() {};
    console.log(anonymousFunction.name); // 输出: ""
  3.  `prototype` ：
    - 每个函数都有一个 `prototype` 属性，指向一个对象，该对象包含所有实例共享的属性和方法。通常用于构造函数。
    function Person(name) {
        this.name = name;
    }
    Person.prototype.sayHello = function() {
        console.log(`Hello, my name is ${this.name}`);
    };

    const alice = new Person('Alice');
    alice.sayHello(); // 输出: "Hello, my name is Alice"
  4.  `caller` （非严格模式下）：
    -  `caller` 属性指向调用当前函数的函数。如果当前函数是由全局代码调用的， `caller` 返回 `null` 。在严格模式下， `caller` 属性是不可用的。
    function outer() {
        inner();
    }

    function inner() {
        console.log(inner.caller); // 输出: outer
    }

    outer();
  5.  `apply`  和  `call` ：
    - 这两个方法是函数对象的内置方法，用于调用函数并指定 `this` 值。
    function greet() {
        console.log(`Hello, ${this.name}`);
    }

    const user = { name: 'Alice' };
    greet.call(user); // 输出: "Hello, Alice"
    greet.apply(user); // 输出: "Hello, Alice"
  6.  `bind` ：
    -  `bind` 方法创建一个新的函数，该函数在调用时将 `this` 关键字设置为提供的值。
    const user = { name: 'Alice' };
    function greet() {
      console.log(`Hello, ${this.name}`);
    }

    const greetAlice = greet.bind(user);
    greetAlice(); // 输出: "Hello, Alice"

  三、总结
  - 函数对象具有许多独特的属性，如 `length` 、 `name` 、 `prototype` 等，这些属性使得函数在JavaScript中不仅仅是执行代码的块，也是可操作的对象。
  - 理解这些属性可以帮助开发者更好地利用函数的特性，进行更复杂的编程任务，如构造函数、方法绑定等。
   -->
</head>
<body>
  
  <script>
    // 1. `length` ：
    // `length` 属性表示函数的形参个数。
    function greet(name) {
      console.log(`Hello, ${name}`);
    }

    console.log("length", greet.length); // 输出: 1

    function bar(a, b, c, ...others) {
      console.log("length", bar.length); // 输出: 3
    }

    bar()

    // 2.  `name` ：
    // `name` 属性表示函数的名称。
    function greet(name) {
      console.log(`Hello, ${name}`);
    }

    console.log(greet.name); // 输出: "greet"

    // 3.  `prototype` ：
    // `prototype` 属性是一个对象，用于存储函数的实例方法。
    function Person(name) {
      this.name = name;
    }

    Person.prototype.sayHello = function () {
      console.log(`Hello, my name is ${this.name}`);
    }

    // 4. `arguments` ：
    // `arguments` 是一个类数组对象，包含了函数调用时传入的所有参数。
    function greet(name) {
      console.log(`Hello, ${name}`);
      console.log(arguments);
    }

    greet("Alice", "Bob", "Charlie"); // 输出: ["Alice", "Bob", "Charlie"]

    // 5. 自定义属性
    function greet(name) {
      console.log(`Hello, ${name}`);
    }

    greet.customProperty = "This is a custom property";

    console.log(greet.customProperty); // 输出: "This is a custom property"

  </script>

</body>
</html>